package cn.com.openportal.ffw.modules.sys.service.impl;

import cn.com.openportal.ffw.common.exception.RRException;
import cn.com.openportal.ffw.cache.utils.CacheUtils;
import cn.com.openportal.ffw.common.utils.Constant;
import cn.com.openportal.ffw.common.utils.PageUtils;
import cn.com.openportal.ffw.modules.sys.entity.SysDeptEntity;
import cn.com.openportal.ffw.modules.sys.entity.SysRoleEntity;
import cn.com.openportal.ffw.modules.sys.query.SysUserQuery;
import cn.com.openportal.ffw.modules.sys.service.*;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import cn.com.openportal.ffw.modules.sys.dao.SysUserDao;
import cn.com.openportal.ffw.modules.sys.entity.SysUserEntity;
import org.apache.commons.lang.RandomStringUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.crypto.hash.Sha256Hash;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * 系统用户
 *
 * @author LeeSon
 */
@Service("sysUserService")
public class SysUserServiceImpl extends ServiceImpl<SysUserDao, SysUserEntity> implements SysUserService {
    @Autowired
    private SysUserRoleService sysUserRoleService;
    @Autowired
    private SysDeptService sysDeptService;
    @Autowired
    private CacheUtils CacheUtils;
    @Autowired
    private SysUserTokenService sysUserTokenService;
    @Autowired
    private SysRoleService sysRoleService;

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        String username = (String) params.get("username");
        //Long createUserId = (Long) params.get("createUserId");
        List<Long> deptIds = (List<Long>) params.get("deptIds");
        if(null!=deptIds){
            if(deptIds.size()==0){
                deptIds.add(0L);
            }
        }

        IPage<SysUserEntity> page = this.page(
                new SysUserQuery().getPage(params),
                new QueryWrapper<SysUserEntity>()
                        .like(StringUtils.isNotBlank(username), "username", username)
                        //.eq(createUserId != null, "create_user_id", createUserId)
                        .in(null != deptIds && deptIds.size() > 0, "dept_id", deptIds)
        );

        for (SysUserEntity sysUserEntity : page.getRecords()) {
            if (null != sysUserEntity.getDeptId() && 0L != sysUserEntity.getDeptId()) {
                SysDeptEntity sysDeptEntity = sysDeptService.getById(sysUserEntity.getDeptId());
                sysUserEntity.setDeptName(sysDeptEntity.getName());
            } else {
                sysUserEntity.setDeptName("顶级部门");
            }
        }

        return new PageUtils(page);
    }

    @Override
    public List<String> queryAllPerms(Long userId) {
        return baseMapper.queryAllPerms(userId);
    }

    @Override
    public List<Long> queryAllMenuId(Long userId) {
        return baseMapper.queryAllMenuId(userId);
    }

    @Override
    public SysUserEntity queryByUserName(String username) {
        return baseMapper.queryByUserName(username);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveUser(SysUserEntity user) {
        user.setCreateTime(new Date());
        //sha256加密
        String salt = RandomStringUtils.randomAlphanumeric(20);
        user.setPassword(new Sha256Hash(user.getPassword(), salt).toHex());
        user.setSalt(salt);
        this.save(user);

        //检查角色是否越权
        checkRole(user);

        //保存用户与角色关系
        sysUserRoleService.saveOrUpdate(user.getUserId(), user.getRoleIdList());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void update(SysUserEntity user) {
        if (StringUtils.isBlank(user.getPassword())) {
            user.setPassword(null);
        } else {
            user.setPassword(new Sha256Hash(user.getPassword(), user.getSalt()).toHex());
        }
        this.updateById(user);
        //CacheUtils.delCache(Constant.SYSUSERENTITY, "update");
        CacheUtils.removeCacheKey(Constant.SYSUSERENTITY, user.getUserId().toString(), "update");

        //检查角色是否越权
        checkRole(user);

        //保存用户与角色关系
        sysUserRoleService.saveOrUpdate(user.getUserId(), user.getRoleIdList());

        sysUserTokenService.logout(user.getUserId());
    }

    @Override
    public void deleteBatch(Long[] userIds) {
        this.removeByIds(Arrays.asList(userIds));
        sysUserRoleService.deleteBatchByUser(userIds);

        //CacheUtils.delCache(Constant.SYSUSERENTITY, "deleteBatch");

        for (Long userId : userIds) {
            CacheUtils.removeCacheKey(Constant.SYSUSERENTITY, userId.toString(), "deleteBatch");
            sysUserTokenService.logout(userId);
        }
    }

    @Override
    public boolean updatePassword(Long userId, String password, String newPassword, String email, String mobile) {
        SysUserEntity userEntity = new SysUserEntity();
        userEntity.setPassword(newPassword);
        userEntity.setEmail(email);
        userEntity.setMobile(mobile);
        boolean result = this.update(userEntity,
                new QueryWrapper<SysUserEntity>().eq("user_id", userId).eq("password", password));
        if (result) {
            //CacheUtils.delCache(Constant.SYSUSERENTITY, "updatePassword");
            CacheUtils.removeCacheKey(Constant.SYSUSERENTITY, userId.toString(), "updatePassword");
            sysUserTokenService.logout(userId);
        }
        return result;
    }

    /**
     * 检查角色是否越权
     */
    private void checkRole(SysUserEntity user) {

        if (getUserId() == Constant.SUPER_ADMIN) {
            return;
        }

        if (user.getRoleIdList() == null || user.getRoleIdList().size() == 0) {
            return;
        }

        //如果不是超级管理员，则需要判断用户的角色是否自己创建
        //List<Long> roleIdList = sysRoleService.queryRoleIdList(user.getCreateUserId());

        List<Long> roleIdList = getRoleIdList();
        //判断是否越权
        if (!roleIdList.containsAll(user.getRoleIdList())) {
            //throw new RRException("用户所选角色，不是本人创建");
            throw new RRException("用户所选角色，权限限制");
        }
    }

    private List<Long> getRoleIdList(){
        List<Long> roleIdList = new ArrayList<>();
        SysUserEntity sysUserEntity = getUser();
        List<Long> deptIds = sysDeptService.getSubDeptIdList(sysUserEntity.getDeptId());
        deptIds.add(sysUserEntity.getDeptId());
        List<SysRoleEntity> roleList = sysRoleService.getBaseMapper().selectList(new QueryWrapper<SysRoleEntity>()
                .select("role_id")
                .in(null != deptIds && deptIds.size() > 0, "dept_id", deptIds));
        for (SysRoleEntity e : roleList) {
            roleIdList.add(e.getRoleId());
        }
        return  roleIdList;
    }

    private SysUserEntity getUser() {
        return (SysUserEntity) SecurityUtils.getSubject().getPrincipal();
    }

    private  Long getUserId() {
        return getUser().getUserId();
    }
}
